#!/bin/bash

# 初始化默认参数
OLD_DIR=""
NEW_DIR=""
OUTPUT_DIR="."

# 打印错误信息并退出
error_exit() {
    echo "Error: $1" >&2
    exit 1
}

# 解析命令行参数
parse_args() {
    while getopts "s:d:o:" opt; do
        case $opt in
            s) OLD_DIR="$OPTARG" ;;
            d) NEW_DIR="$OPTARG" ;;
            o) OUTPUT_DIR="$OPTARG" ;;
            \?) error_exit "Invalid option: -$OPTARG" ;;
            :) error_exit "Option -$OPTARG requires an argument." ;;
        esac
    done

    # 校验必填参数
    if [ -z "$OLD_DIR" ] || [ -z "$NEW_DIR" ]; then
        error_exit "Missing required arguments. Usage: $0 -s <old_dir> -d <new_dir> [-o <output_dir>]"
    fi

    # 校验目录存在性
    if [ ! -d "$OLD_DIR" ]; then
        error_exit "Old directory '$OLD_DIR' does not exist or is not a directory"
    fi
    if [ ! -d "$NEW_DIR" ]; then
        error_exit "New directory '$NEW_DIR' does not exist or is not a directory"
    fi

    # 创建输出目录（若不存在）
    mkdir -p "$OUTPUT_DIR" || error_exit "Failed to create output directory '$OUTPUT_DIR'"
}

# 判断文件是否为二进制文件（优化识别逻辑，覆盖静态库、动态库等）
is_binary_file() {
    local file="$1"
    local file_output=$(file -b "$file")  # -b 仅输出描述，不含文件名

    # 匹配常见二进制文件类型：
    # 1. 明确标记 binary/data
    # 2. 静态库（ar archive）
    # 3. 动态库（shared object）
    # 4. ELF 可执行文件
    # 5. 其他二进制格式（如 Mach-O、PE 等）
    if echo "$file_output" | grep -qiE \
        "binary|data|ar archive|shared object|elf|mach-o|pe32|pe32\+|ms-dos executable|compressed"; then
        return 0  # 是二进制文件
    else
        return 1  # 是文本文件
    fi
}

# 处理「新旧目录都存在」的文件（生成patch或复制二进制）
process_existing_file() {
    local old_file="$1"
    local new_file="$2"
    local rel_path="${old_file#$OLD_DIR/}"  # 保留原始相对路径

    # 输出路径：保留完整目录结构
    local output_path="$OUTPUT_DIR/$rel_path"
    local output_dir=$(dirname "$output_path")

    # 创建输出目录（确保路径存在）
    mkdir -p "$output_dir" || {
        echo "Warning: Failed to create output directory '$output_dir', skipping file" >&2
        return 1
    }

    # 情况1：二进制文件 - 直接复制新文件到输出目录（保留路径）
    if is_binary_file "$new_file"; then
        cp -f "$new_file" "$output_path" || {
            echo "Warning: Failed to copy binary file '$new_file' to '$output_path'" >&2
            return 1
        }
        echo "Copied binary file (updated): $rel_path"
        return 0
    fi

    # 情况2：文本文件 - 生成 git 风格 patch
    local patch_file="${output_path}.patch"
    # diff -u 生成统一格式patch，--label模拟git的a/b路径格式
    diff -u --label "a/$rel_path" --label "b/$rel_path" "$old_file" "$new_file" > "$patch_file" || {
        # diff返回1表示有差异（正常），其他返回值为错误
        if [ $? -ne 1 ]; then
            echo "Warning: Failed to generate patch for '$rel_path'" >&2
            rm -f "$patch_file"
            return 1
        fi
    }

    # 移除空patch（无差异时）
    if [ ! -s "$patch_file" ]; then
        rm -f "$patch_file"
        echo "No changes detected: $rel_path"
    else
        echo "Generated patch: ${rel_path}.patch"
    fi
}

# 处理「仅新目录存在」的文件（新添加的文件，包括二进制和文本）
process_new_file() {
    local new_file="$1"
    local rel_path="${new_file#$NEW_DIR/}"  # 保留原始相对路径

    # 输出路径：保留完整目录结构
    local output_path="$OUTPUT_DIR/$rel_path"
    local output_dir=$(dirname "$output_path")

    # 创建输出目录
    mkdir -p "$output_dir" || {
        echo "Warning: Failed to create output directory '$output_dir', skipping new file" >&2
        return 1
    }

    # 情况1：新添加的二进制文件 - 直接复制（已修复语法和识别逻辑）
    if is_binary_file "$new_file"; then
        cp -f "$new_file" "$output_path" || {
            echo "Warning: Failed to copy new binary file '$new_file' to '$output_path'" >&2
            return 1
        }
        echo "Copied new binary file: $rel_path"
        return 0
    fi

    # 情况2：新添加的文本文件 - 生成完整文件的patch（模拟git add）
    local patch_file="${output_path}.patch"
    # 使用 diff 创建「新增文件」的patch（从/dev/null对比）
    diff -u --label "/dev/null" --label "b/$rel_path" /dev/null "$new_file" > "$patch_file" || {
        echo "Warning: Failed to generate patch for new file '$rel_path'" >&2
        rm -f "$patch_file"
        return 1
    }

    echo "Generated patch for new file: ${rel_path}.patch"
}

# 递归处理所有文件（包括新旧文件和新增文件）
process_all_files() {
    echo "Starting to process files from '$OLD_DIR' to '$NEW_DIR'..."
    echo "Output will be saved to '$OUTPUT_DIR'"

    # 处理新目录中所有文件，分「已存在」和「新增」两类
    find "$NEW_DIR" -type f | while read -r new_file; do
        local rel_path="${new_file#$NEW_DIR/}"
        local old_file="$OLD_DIR/$rel_path"

        # 检查旧文件是否存在，分支处理
        if [ -f "$old_file" ]; then
            process_existing_file "$old_file" "$new_file"
        else
            process_new_file "$new_file"
        fi
    done

    echo -e "\nProcessing completed. Check output directory: $OUTPUT_DIR"
}

# 主函数
main() {
    parse_args "$@"
    process_all_files
}

# 启动脚本
main "$@"
